package com.michael.demos.base.java.arithmetic;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * 类功能描述:
 * <pre>
 *   随机密码生成器
 * </pre>
 *
 * @author Michael
 * @version 1.0
 * @date 2021/03/12 16:59
 */
public class PasswordGenerator {

    private static final char[] SOURCE_NUMBER = "0123456789".toCharArray();
    private static final char[] SOURCE_LETTER_UNDER = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    private static final char[] SOURCE_LETTER_UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    private static final char[] SOURCE_SPECIAL = "!@#$%^&*".toCharArray();

    public static void main(String[] args) {

        //System.out.println(LocalDateTime.of(2011,5,20,13,14,20).toInstant(ZoneOffset.of("+8")).toEpochMilli());

        System.out.println(gen16());
        System.out.println(gen16());
        System.out.println(gen16());
        System.out.println(gen64());

        String result = gen16();
        System.out.println(gen16());
        System.out.println(result);
        System.out.println(getNewString(result));
        System.out.println(getNewString(result));
        System.out.println(getNewString(result));

        //for (int i = 0; i < 1000; i++) {
        //    //System.out.println(gen16());
        //    System.out.println(gen64());
        //}
    }

    private static String gen128() {
        return gen(128);
    }

    private static String gen64() {
        return gen(64);
    }

    private static String gen32() {
        return gen(32);
    }

    private static String gen16() {
        return gen(16);
    }

    private static String gen(int len) {
        if (len < 16) {
            return null;
        }
        // 1. 按比例规划 数字、大小写字母、特殊字符 的数量
        int specialSize = len >> 3;
        int underSize = (len >> 2) + (len >> 4);
        int upperSize = underSize;
        int numberSize = len >> 2;

        // 2. 随机抽取对应数量的 字符 组成字符数组

        char[] result = new char[len];
        Random random = new Random();
        int randomMax = 100000;
        for (int i = 0; i < len; i++) {
            char c = 0;
            while (c == 0) {
                int nextInt = random.nextInt(randomMax);
                int index = nextInt % (4 + 1);
                switch (index) {
                    case 1:
                        if (specialSize > 0) {
                            c = SOURCE_SPECIAL[nextInt % SOURCE_SPECIAL.length];
                            specialSize--;
                        }
                        break;
                    case 2:
                        if (numberSize > 0) {
                            c = SOURCE_NUMBER[nextInt % SOURCE_NUMBER.length];
                            numberSize--;
                        }
                        break;
                    case 3:
                        if (underSize > 0) {
                            c = SOURCE_LETTER_UNDER[nextInt % SOURCE_LETTER_UNDER.length];
                            underSize--;
                        }
                        break;
                    case 4:
                        if (upperSize > 0) {
                            c = SOURCE_LETTER_UPPER[nextInt % SOURCE_LETTER_UPPER.length];
                            upperSize--;
                        }
                        break;
                    default:
                        break;
                }
            }
            result[i] = c;
        }

        String stringResult = new String(result);

        System.out.println(stringResult + " -> Source");
        // 3. 字符数组打乱顺序
        // 4. 输出
        return getNewString(stringResult);
    }

    /** String 乱序后输出 */
    public static String getNewString(String sourceString) {

        char[] chars = sourceString.toCharArray();
        String[] strs = new String[chars.length];
        for (int i = 0; i < chars.length; i++) {
            strs[i] = chars[i] + "";
        }
        List<String> list = Arrays.asList(strs);
        Collections.shuffle(list);
        StringBuilder sb = new StringBuilder();
        for(String c : list) {
            sb.append(c);
        }

        return sb.toString();
    }
}
